package com.aierjun.camera.photo;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.ExifInterface;
import android.media.SoundPool;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.Toast;

import com.aierjun.camera.AppInit;
import com.aierjun.camera.R;
import com.aierjun.camera.common.ViewParamsCallback;
import com.aierjun.camera.manager.CameraManager;
import com.aierjun.camera.sensor.SensorControler;
import com.aierjun.camera.utils.BitmapUtils;
import com.aierjun.camera.utils.FileUtil;
import com.aierjun.camera.widget.FocusImageView;
import com.aierjun.camera.widget.PhotoCameraView;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

import static android.media.ExifInterface.TAG_DATETIME;
import static android.media.ExifInterface.TAG_GPS_LATITUDE;
import static android.media.ExifInterface.TAG_GPS_LONGITUDE;
import static android.media.ExifInterface.TAG_ORIENTATION;

public class TakePhotoManager implements TakePhotoManagerInterface {

    private SensorControler mSensorControler;
    private PhotoCameraView mPhotoCameraView;
    private FocusImageView mFocusImageView;
    private SeekBar zoom_seekbar;

    private int mFocusSoundId;
    private SoundPool mSoundPool;
    private boolean mFocusSoundPrepared;
    private String mImagePath;
    private int cameraWidth = 1200, cameraHeight = 1200, controllerHeight;
    private RelativeLayout controller_rl;
    private ImageView shutterImageView;
    private ImageView backImageView;
    private ImageView btn_lenses;
    private ImageView btnflashlight;
    private String gps_latitude = "";
    private String gps_longitude = "";

    private RelativeLayout.LayoutParams paramsController;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

        }
    };

    private Activity activity;
    private static TakePhotoManager self;

    public static TakePhotoManager getInstance(Activity activity) {
        if (self == null)
            self = new TakePhotoManager(activity);
        return self;
    }

    public TakePhotoManager(Activity activity) {
        this.activity = activity;
    }

    public TakePhotoManager initCamera(PhotoCameraView photoCameraView) {
        mPhotoCameraView = photoCameraView;
        photoCameraView.bindActivity(activity);
        photoCameraView.setOnCameraPrepareListener(new PhotoCameraView.OnCameraPrepareListener() {
            @Override
            public void onPrepare(CameraManager.CameraDirection cameraDirection) {
                //在这里相机已经准备好 可以获取maxZoom
                zoom_seekbar.setMax(mPhotoCameraView.getMaxZoom());
                if (cameraDirection == CameraManager.CameraDirection.CAMERA_BACK) {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            int screenWidth = AppInit.mScreenWidth;
                            Point point = new Point(screenWidth / 2, screenWidth / 2);
                            onCameraFocus(point);
                        }
                    }, 800);
                }
            }
        });
        photoCameraView.setSwitchCameraCallBack(new PhotoCameraView.SwitchCameraCallBack() {
            @Override
            public void switchCamera(boolean isSwitchFromFront) {
                if (isSwitchFromFront) {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            int screenWidth = AppInit.mScreenWidth;
                            Point point = new Point(screenWidth / 2, screenWidth / 2);
                            onCameraFocus(point);
                        }
                    }, 300);
                }
            }
        });

        photoCameraView.setPictureCallback(new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                new SavePicTask(data, mPhotoCameraView.isBackCamera()).start();
            }
        });

        photoCameraView.setViewParamsCallback(new ViewParamsCallback() {
            @Override
            public void callBackParams(ViewGroup.LayoutParams params) {
//                Log.d("Ani",SweetApplication.mScreenHeight + " ------------ " + params.height);
                controllerHeight = AppInit.mScreenHeight - params.height;
                if (controllerHeight < 400)
                    controllerHeight = 400;
                if (controller_rl != null) {
                    if (paramsController == null) {
                        paramsController = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, controllerHeight);
                        paramsController.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                    }
                    controller_rl.setBackgroundColor(activity.getResources().getColor(R.color.font4));
                    controller_rl.setLayoutParams(paramsController);
                    controller_rl.setVisibility(View.VISIBLE);
                }
            }
        });
        return this;
    }

    public TakePhotoManager initFocusImageView(FocusImageView focusImageView) {
        mFocusImageView = focusImageView;
        return this;
    }

    public TakePhotoManager initControllerRLChildView(RelativeLayout controller_rl, ImageView backImageView, ImageView shutterImageView, ImageView btn_lenses, ImageView btn_flashlight) {
        this.controller_rl = controller_rl;
        this.backImageView = backImageView;
        this.shutterImageView = shutterImageView;
        this.btn_lenses = btn_lenses;
        this.btnflashlight = btn_flashlight;

        backImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                activity.finish();
            }
        });
        shutterImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                takePicture();
            }
        });
        btn_lenses.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPhotoCameraView.switchCamera();
            }
        });
        btnflashlight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPhotoCameraView.switchFlashMode();
                CameraManager.FlashLigthStatus flashLigthStatus = CameraManager.getInstance(activity).getLightStatus();
                if (flashLigthStatus == CameraManager.FlashLigthStatus.LIGHT_AUTO) {
                    btnflashlight.setImageDrawable(activity.getResources().getDrawable(R.drawable.camera_icon_flashlight_auto));
                } else if (flashLigthStatus == CameraManager.FlashLigthStatus.LIGHT_ON) {
                    btnflashlight.setImageDrawable(activity.getResources().getDrawable(R.drawable.camera_icon_flashlight_on));
                } else if (flashLigthStatus == CameraManager.FlashLigthStatus.LIGTH_OFF) {
                    btnflashlight.setImageDrawable(activity.getResources().getDrawable(R.drawable.camera_icon_flashlight_off));
                }
            }
        });
        return this;
    }

    public TakePhotoManager initSensorControler() {
        mSensorControler = SensorControler.getInstance();

        mSensorControler.setCameraFocusListener(new SensorControler.CameraFocusListener() {
            @Override
            public void onFocus() {
                int screenWidth = AppInit.mScreenWidth;
                Point point = new Point(screenWidth / 2, screenWidth / 2);

                onCameraFocus(point);
            }
        });
        return this;
    }

    public TakePhotoManager initZoomSeekBar(SeekBar zoom_seekbar) {
        this.zoom_seekbar = zoom_seekbar;
        //禁止手动操作seekbar
        zoom_seekbar.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
        return this;
    }

    /**
     * 相机对焦  默认不需要延时
     *
     * @param point
     */
    private void onCameraFocus(final Point point) {
        onCameraFocus(point, false);
    }

    /**
     * 相机对焦
     *
     * @param point
     * @param needDelay 是否需要延时
     */
    private void onCameraFocus(final Point point, boolean needDelay) {
        long delayDuration = needDelay ? 300 : 0;

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (!mSensorControler.isFocusLocked()) {
                    if (mPhotoCameraView.onFocus(point, autoFocusCallback)) {
                        mSensorControler.lockFocus();
                        mFocusImageView.startFocus(point);

                        //播放对焦音效
                        if (mFocusSoundPrepared) {
                            mSoundPool.play(mFocusSoundId, 1.0f, 0.5f, 1, 0, 1.0f);
                        }
                    }
                }
            }
        }, delayDuration);
    }

    private final Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {

        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            //聚焦之后根据结果修改图片
            if (success) {
                mFocusImageView.onFocusSuccess();
            } else {
                //聚焦失败显示的图片，由于未找到合适的资源，这里仍显示同一张图片
                mFocusImageView.onFocusFailed();
            }
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //一秒之后才能再次对焦
                    mSensorControler.unlockFocus();
                }
            }, 1000);
        }
    };

    private SoundPool getSoundPool() {
        if (mSoundPool == null) {
            mSoundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
            mFocusSoundId = mSoundPool.load(activity, R.raw.camera_focus, 1);
            mFocusSoundPrepared = false;
            mSoundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
                @Override
                public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                    mFocusSoundPrepared = true;
                }
            });
        }
        return mSoundPool;
    }


    public void onStart() {
        mSensorControler.onStart();

        if (mPhotoCameraView != null) {
            mPhotoCameraView.onStart();
        }

        mSoundPool = getSoundPool();
    }


    public void onStop() {
        mSensorControler.onStop();

        if (mPhotoCameraView != null) {
            mPhotoCameraView.onStop();
        }

        mSoundPool.release();
        mSoundPool = null;

    }


    public void onDestroy() {
        mPhotoCameraView.releaseCamera();

    }

    public boolean takePicture() {
        boolean flag = mPhotoCameraView.takePicture();
        if (!flag) {
            mSensorControler.unlockFocus();
        }
        return flag;
    }

    /**
     * 记录是拖拉照片模式还是放大缩小照片模式
     */

    private static final int MODE_INIT = 0;
    /**
     * 放大缩小照片模式
     */
    private static final int MODE_ZOOM = 1;
    private int mode = MODE_INIT;// 初始状态

    private float startDis;

    public boolean onTouchEvent(MotionEvent event) {
/** 通过与运算保留最后八位 MotionEvent.ACTION_MASK = 255 */
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            // 手指压下屏幕
            case MotionEvent.ACTION_DOWN:
                mode = MODE_INIT;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                //如果mZoomSeekBar为null 表示该设备不支持缩放 直接跳过设置mode Move指令也无法执行
                if (zoom_seekbar == null) return true;
                //移除token对象为mZoomSeekBar的延时任务
                mHandler.removeCallbacksAndMessages(zoom_seekbar);
//                mZoomSeekBar.setVisibility(View.VISIBLE);
                zoom_seekbar.setVisibility(View.GONE);

                mode = MODE_ZOOM;
                /** 计算两个手指间的距离 */
                startDis = spacing(event);
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == MODE_ZOOM) {
                    zoom_seekbar.setVisibility(View.VISIBLE);
                    //只有同时触屏两个点的时候才执行
                    if (event.getPointerCount() < 2) return true;
                    float endDis = spacing(event);// 结束距离
                    //每变化10f zoom变1
                    int scale = (int) ((endDis - startDis) / 10f);
                    if (scale >= 1 || scale <= -1) {
                        int zoom = mPhotoCameraView.getZoom() + scale;
                        //zoom不能超出范围
                        if (zoom > mPhotoCameraView.getMaxZoom())
                            zoom = mPhotoCameraView.getMaxZoom();
                        if (zoom < 0) zoom = 0;
                        mPhotoCameraView.setZoom(zoom);
                        zoom_seekbar.setMax(mPhotoCameraView.getMaxZoom());
                        zoom_seekbar.setProgress(zoom);
                        //将最后一次的距离设为当前距离
                        startDis = endDis;
                    }
                }
                break;
            // 手指离开屏幕
            case MotionEvent.ACTION_UP:
                if (mode != MODE_ZOOM) {
                    //设置聚焦
                    Point point = new Point((int) event.getX(), (int) event.getY());
                    onCameraFocus(point);
                } else {
                    //ZOOM模式下 在结束两秒后隐藏seekbar 设置token为mZoomSeekBar用以在连续点击时移除前一个定时任务
                    mHandler.postAtTime(new Runnable() {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            zoom_seekbar.setVisibility(View.GONE);
                        }
                    }, zoom_seekbar, SystemClock.uptimeMillis() + 2000);
                }
                break;
        }
        return true;

    }

    @Override
    public void setLocation(String gps_latitude, String gps_longitude) {
        this.gps_latitude = gps_latitude;
        this.gps_longitude = gps_longitude;
    }


    /**
     * 两点的距离
     */
    private float spacing(MotionEvent event) {
        if (event == null) {
            return 0;
        }
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }


    private class SavePicTask extends Thread {
        private byte[] data;
        private boolean isBackCamera;
        private boolean sampleSizeSuggested;
        private boolean ioExceptionRetried;     //寻找合适的bitmap发生io异常  允许一次重试


        SavePicTask(byte[] data, boolean isBackCamera) {
            sampleSizeSuggested = false;
            ioExceptionRetried = false;
            this.data = data;
            this.isBackCamera = isBackCamera;
        }

        @Override
        public void run() {
            super.run();
            Message msg = handler.obtainMessage();
            msg.obj = saveToSDCard(data);
            msg.what = 123456;
            handler.sendMessage(msg);
        }

        /**
         * 将拍下来的照片存放在SD卡中
         *
         * @param data
         * @return imagePath 图片路径
         */
        public String saveToSDCard(byte[] data) {
            mImagePath = FileUtil.getCameraImgPath();

            InputStream is = null;
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = false;
                options.inSampleSize = 1;
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                options.inPurgeable = true;
                options.inInputShareable = true;

                is = new ByteArrayInputStream(data);

                Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);

                Bitmap bitmapNew = BitmapUtils.rotateImage(bitmap, 90);

                if (bitmap != null && bitmap != bitmapNew)
                    bitmap.recycle();

                boolean isSave = BitmapUtils.saveBitmap(bitmapNew, mImagePath);

                if (isSave) {
                    ExifInterface exifInterface = new ExifInterface(mImagePath);
                    exifInterface.setAttribute(TAG_DATETIME, DateFormat.format("yyyy-MM-dd HH:mm:ss",new Date()) + "");
                    exifInterface.setAttribute(TAG_GPS_LATITUDE, gps_latitude);
                    exifInterface.setAttribute(TAG_GPS_LONGITUDE, gps_longitude);
                    exifInterface.saveAttributes();
                    ExifInterface exifInterfaceN = new ExifInterface(mImagePath);
                    Log.i("Ani EXIF", exifInterfaceN.getAttribute(TAG_DATETIME)
                            + " : " + exifInterfaceN.getAttribute(TAG_GPS_LATITUDE) + " : "
                            + exifInterfaceN.getAttribute(TAG_GPS_LONGITUDE));
                    return mImagePath;
                }
                if (!bitmapNew.isRecycled())
                    bitmapNew.recycle();

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (is != null)
                        is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            //直接写文件，bug旋转角度问题
//            File imgFile = new File(mImagePath);
//
//            FileOutputStream outputStream = null;
//            FileChannel fileChannel = null;
//            ByteBuffer buffer = null;
//            try {
//                outputStream = new FileOutputStream(imgFile);
//                fileChannel = outputStream.getChannel();
//                buffer = ByteBuffer.allocate(data.length);
//                buffer.put(data);
//                buffer.flip();
//                fileChannel.write(buffer);
//            } catch (IOException e) {
//                Log.e("Ani", e.getMessage());
//            } finally {
//                try {
//                    if (outputStream != null)
//                        outputStream.close();
//                    if (fileChannel != null)
//                        fileChannel.close();
//                    if (buffer != null) {
//                        buffer.clear();
//                    }
//                } catch (IOException e) {
//                    Log.e("Ani", e.getMessage());
//                }
//            }


//            try {
//                ExifInterface exif = new ExifInterface(mImagePath);
//                int droneLatitude = 152;
//                int droneLongitude = 135;
//                if (droneLatitude != 0 || droneLongitude != 0) {
//                    exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, droneLongitude + "");
//                    exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, droneLatitude + "");
//                }
//                exif.setAttribute("Location",droneLatitude + " : " + droneLongitude);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }

            return mImagePath;
        }

        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == 123456)
                    Toast.makeText(activity, (String) msg.obj, Toast.LENGTH_SHORT).show();
                //解决拍后卡住的问题
                try {
                    mPhotoCameraView.startPreview();
                } catch (Throwable e) {
                    e.printStackTrace();
                }


//                try {
//                    ExifInterface exif = new ExifInterface(mImagePath);
//
//                    String longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
//                    String latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
//
//                    Log.d("Ani", longitude + " : " + latitude + " : " + exif.getAttribute("Location"));
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }

            }
        };
    }
}
